概览
Agent 和聊天助手相比,只是多了可以应用工具的部分,而 Dify 中支持了很多的工具,甚至可以后期自定义添加工具。
Agent
接口信息
调用 /console/api/apps/xxx/chat-messages
接口,调用 AgentChatAppGenerator.generate 方法,app_model.mode 是 ‘agent-chat’。
流程详解
AgentChatAppGenerator.generate 中,先获取 conversation
然后根据 app_model 和 conversation 获取 app model config, 如果是 debug 模式,则允许用户传递的 model config 覆盖 据 app_model 和 conversation 查询出来的
解析文件得到 file_objs
转换为 app config
初始化 application generate entity
初始化 generate records
初始化 queue manager
启动线程,调用 _generate_worker 方法
判断 token 数量是否足够
重新组织 prompt message
进行敏感词检测
标注回复
填写来自外部数据工具的变量输入,获取上下文信息
再次重新组织 prompt message
再次敏感词检测
加载工具变量
初始化 model 实例
组织 prompt message
根据LLM模型确认使用 FUNCTION_CALLING 模式还是 CHAIN_OF_THOUGHT(CoT + ReAct)。如果模型支持 MULTI_TOOL_CALL 或 TOOL_CALL,则使用 FUNCTION_CALLING 。否则使用 CHAIN_OF_THOUGHT 模式。
获取 AgentRunner 对象,并且调用 run 方法。如果是 CHAIN_OF_THOUGHT 模式,且LLM模式是 CHAT模式,则使用 CotChatAgentRunner。如果是 CHAIN_OF_THOUGHT 模式,且LLM模式是 COMPLETION 模式,则使用 CotCompletionAgentRunner。如果是 FUNCTION_CALLING 模式,则使用 FunctionCallAgentRunner
得到 response,将 response 转换后返回出去
具体详细的 AgentRunner.run 方法的核心逻辑如下:
AgentRunner | 核心逻辑 |
---|---|
FunctionCallAgentRunner | 1. 第一步就是调用 self._init_prompt_tools 方法,得到 tool_instances, prompt_messages_tools 2. 获取调用的最大步数 max_iteration_steps 3. while 循环运行每一步,直到步数达到 max_iteration_steps,或者 function_call_state 为 False 4. 循环第一步会组织 prompt 和 计算 max tokens 5. 循环中会先进行大模型的调用,model_instance.invoke_llm 得到 chunks 6. 循环chunks,判断每个 chunk 是否有工具调用(大模型选择出工具) 7. 如果没有选择出工具,则大模型返回出什么,就 yield 出什么 8. 如果选择出了工具,那么就在下面循环调用每个工具。然后再次进行循环。 9. 再次循环时候,prompt 就会更新,带上选出的工具信息,然后再次调用大模型。 |
CotChatAgentRunner | 1. 大致流程和上述一致,只是没有了 tools,而是判断是否有 action。如果没有 action,直接返回最终答案 2. 否则则判断 action 是否为 final answer。如果不是,则去调用每一个 action。 3. 然后重复上述步骤,直到步数达到 max_iteration_steps,或者 function_call_state 为 False |
CotCompletionAgentRunner | 同上 |
总结
Q:Agent 应用中,如果模型不支持 function call 时怎么办?
A:不支持则使用 ReAct 模式,如下所示,当 LLM 切换为 DeepSeek 时,显示如下:
Q:怎么添加和拓展工具?
A:工具的添加和模型的添加类似,都是需要提供 yaml 文件和相对应的代码。可参考此处
Q:在 Agent 中,如果匹配不到对应的工具类怎么处理?
A:不同大模型的能力不同,假如使用了三个工具,但是只匹配到一个工具,那么就使用这个工具。如果一个都没有匹配到,那么就返回大模型的输出。